/**  
* Copyright (c) 2008, Noel Lynch All rights reserved. Redistribution and use  
* in source and binary forms, with or without modification, are permitted  
* provided that the following conditions are met: Redistributions of source  
* code must retain the above copyright notice, this list of conditions and the  
* following disclaimer. Redistributions in binary form must reproduce the above  
* copyright notice, this list of conditions and the following disclaimer in the  
* documentation and/or other materials provided with the distribution. Neither  
* the name of Noel Lynch nor the names of contributors may be used to  
* endorse or promote products derived from this software without specific prior  
* written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A  
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR  
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,  
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;  
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR  
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF  
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
*/
// Sep 4, 2008

package com.sceneworker.util.swing.timelineeditor;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

public class TimeSliderPanel extends KeyFrameTimeLanePanelComponent implements MouseListener, MouseMotionListener {

	static		final	public		Dimension	kMaxDim = new Dimension(800, 20);
	
	private		float			mf_start;
	private		float			mf_end;
	
	private		int			mi_dragMode;
	
	private		TimeSliderListener		mcl_listener;
	
	public TimeSliderPanel(KeyFrameTimeLinePanel cl_parent) {
		super(cl_parent);
		
		addMouseListener(this);
		addMouseMotionListener(this);
	}
	
	public	void	setTimeSliderListener(TimeSliderListener cl_l) {
		mcl_listener = cl_l;
	}
	
	public	float		getStart() { return mf_start; }
	public	float		getEnd() { return mf_end; }
	
	public	void	setStart(float i_st) { mf_start = i_st; }
	public	void	setEnd(float i_end) { mf_end = i_end; }
	
	public	void	setStartAndEnd(int i_st, int i_end) {
		mf_start = i_st;
		mf_end = i_end;
	}
	
	@Override
	public Dimension getMaximumSize() {
		Dimension		lcl_dim = super.getMaximumSize();
		return new Dimension(lcl_dim.width, 20);
	}

	@Override
	public Dimension getMinimumSize() {
		Dimension		lcl_dim = super.getMinimumSize();
		return new Dimension(lcl_dim.width, 20);
	}

	@Override
	public Dimension getPreferredSize() {
		Dimension		lcl_dim = super.getPreferredSize();
		return new Dimension(lcl_dim.width, 20);
	}

	@Override
	protected	void	paintComponent(Graphics cl_g) {
		Graphics2D		lcl_g = (Graphics2D)cl_g.create();
	
		drawBackgroud(lcl_g);
		
		drawSlider(lcl_g);
		
		lcl_g.dispose();
	}
	
	private	Rectangle	getSliderBarRect() {
		int		li_timeLineStart = mcl_parent.getStartTimeOfBar();
		int		li_timeLineEnd = mcl_parent.getEndTimeOfBar();
		int		li_pxPerSecond = mcl_parent.getPixelsPerSecond();
		
		float		li_stRef = mf_start - li_timeLineStart;
		if(li_stRef > li_timeLineEnd) { return null; }
		
		float		li_endRef = mf_end - li_timeLineStart;
		li_endRef -= li_stRef;
		
		int		li_x = (int)(li_stRef * li_pxPerSecond);
		int		li_w = (int)(li_endRef * li_pxPerSecond);
		
		return new Rectangle(li_x, getHeight() >> 1, li_w, getHeight() >> 1);
	}
	
	private	void	drawSlider(Graphics2D cl_g) {
		System.out.println("st = " + mf_start + " : end = " + mf_end);
		Rectangle		lcl_dim = getSliderBarRect();
		
		if(lcl_dim == null) { return; }
		
		GradientPaint		lcl_gpaint = new GradientPaint(lcl_dim.x + (lcl_dim.width >> 1), 0, new Color(0, 120, 255), 
				lcl_dim.x + (lcl_dim.width >> 1), lcl_dim.height >> 1, Color.white, true);
		cl_g.setPaint(lcl_gpaint);
		cl_g.fill(lcl_dim);
		
		cl_g.setColor(Color.red);
		cl_g.fillRect(lcl_dim.x, lcl_dim.y, 10, lcl_dim.height);
		cl_g.fillRect(lcl_dim.x + lcl_dim.width - 10, lcl_dim.y, 10, lcl_dim.height);
		cl_g.setColor(Color.black);
		cl_g.drawRect(lcl_dim.x + lcl_dim.width - 10, lcl_dim.y, 10, lcl_dim.height - 1);
	}
	
	private	void	drawBackgroud(Graphics2D cl_g) {
		cl_g.setColor(Color.white);
		cl_g.fillRect(0, 0, getWidth(), getHeight());
	}

	public void mouseDragged(MouseEvent cl_e) {
		switch(mi_dragMode) {
			case	0:
				dragBar(cl_e.getPoint());
				break;
				
			case	1:
				dragStart(cl_e.getPoint());
				break;
				
			case	2:
				dragEnd(cl_e.getPoint());
				break;
				
		}
	}
	
	private	void	dragEnd(Point cl_pt) {
		int		li_timeLineStart = mcl_parent.getStartTimeOfBar();
		int		li_timeLineEnd = mcl_parent.getEndTimeOfBar();
		int		li_totalTime = mcl_parent.getTotalTime();
		int		li_pxPerSecond = mcl_parent.getPixelsPerSecond();
		float	lf_newTime = ((float)cl_pt.x / (float)li_pxPerSecond) + li_timeLineStart;
		
		if(mcl_listener != null) {
			if(mcl_listener.changeEndTime(lf_newTime, mf_end)) {
				mf_end = lf_newTime;
			} else {
				return;
			}
		} else {
			mf_end = lf_newTime;
		}
		
		if(mf_end >= (li_timeLineEnd - 1)) {
			mcl_parent.pushBar(true);
		} else if(mf_end <= li_timeLineStart) {
			mcl_parent.pushBar(false);
		}
		
		repaint();
	}
	
	private	void	dragStart(Point cl_pt) {
		int		li_timeLineStart = mcl_parent.getStartTimeOfBar();
		int		li_timeLineEnd = mcl_parent.getEndTimeOfBar();
		int		li_totalTime = mcl_parent.getTotalTime();
		int		li_pxPerSecond = mcl_parent.getPixelsPerSecond();
		float	li_newTime = ((float)cl_pt.x / (float)li_pxPerSecond) + li_timeLineStart;
		
		if(mcl_listener != null) {
			if(mcl_listener.changeStartTime(li_newTime, mf_start)) {
				mf_start = li_newTime;
			} else {
				return;
			}
			
		} else {
			mf_start = li_newTime;
		}
		
		
		if(mf_start == li_totalTime) {
			mf_start--;
		}
		
		if(mf_start >= (li_timeLineEnd - 1)) {
			mcl_parent.pushBar(true);
		} else if(mf_start <= li_timeLineStart) {
			mcl_parent.pushBar(false);
		}
		
		repaint();
	}

	// TODO : fix this for listener blocking on end but no start drags...
	private	void	dragBar(Point cl_pt) {
		int		li_timeLineStart = mcl_parent.getStartTimeOfBar();
		int		li_timeLineEnd = mcl_parent.getEndTimeOfBar();
		int		li_totalTime = mcl_parent.getTotalTime();
		int		li_pxPerSecond = mcl_parent.getPixelsPerSecond();
		int		li_newTime = (cl_pt.x / li_pxPerSecond) + li_timeLineStart;
		int		li_endDelta = (int)(mf_end - mf_start);
		int		li_tempStart;
		
		if(mcl_listener != null) {
			if(mcl_listener.changeStartTime(li_newTime, mf_start)) {
				mf_start = li_newTime;
			} else {
				return;
			}
		} else {
			mf_start = li_newTime;
		}
		
		if(mf_start == li_totalTime) {
			mf_start--;
		}
		
		if(mcl_listener != null) {
			if(mcl_listener.changeEndTime(mf_start + li_endDelta, mf_end)) {
				mf_end = mf_start + li_endDelta;
			} else {
				return;
			}
		} else {
			mf_end = mf_start + li_endDelta;
		}
		
		if(mf_start >= (li_timeLineEnd - 1)) {
			mcl_parent.pushBar(true);
		} else if(mf_start <= li_timeLineStart) {
			mcl_parent.pushBar(false);
		}
		
		repaint();
	}
	
	public void mouseMoved(MouseEvent e) {
	}

	public void mouseClicked(MouseEvent arg0) {
	}

	public void mouseEntered(MouseEvent arg0) {
	}

	public void mouseExited(MouseEvent arg0) {
	}

	public void mousePressed(MouseEvent cl_e) {
		Rectangle		lcl_barRect = getSliderBarRect();
		
		if(lcl_barRect == null) { return; }
		
		if(lcl_barRect.contains(cl_e.getPoint())) {
			//mi_dragMode = 0;
			
			Rectangle		lcl_testRect = new Rectangle(lcl_barRect.x, lcl_barRect.y, 10, lcl_barRect.height);
			
			if(lcl_testRect.contains(cl_e.getPoint())) {
				mi_dragMode = 1;
			}
			
			lcl_testRect.x += lcl_barRect.width - 10;
			
			if(lcl_testRect.contains(cl_e.getPoint())) {
				mi_dragMode = 2;
			}
			
		}
		
		
	}

	public void mouseReleased(MouseEvent arg0) {
	}
	
	public	interface	TimeSliderListener {
		boolean	changeStartTime(float i_newTime, float i_oldTime);
		boolean	changeEndTime(float i_newTime, float i_oldTime);
	}
	
}
